package com.solution.action;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;

import com.solution.constant.LoginConstants;
import com.solution.constant.SystemVariableConstants;
import com.solution.delegate.CommunicationServiceDelegate;
import com.solution.delegate.ExaminationServiceDelegate;
import com.solution.delegate.SystemVariableServiceDelegate;
import com.solution.delegate.UserInfoServiceDelegate;
import com.solution.exception.DelegateException;
import com.solution.exception.ServiceBeanException;
import com.solution.form.ExamineeForm;
import com.solution.model.AnswerType;
import com.solution.model.ExamCategoryLevelMapping;
import com.solution.model.ExamType;
import com.solution.model.QuestionType;
import com.solution.model.SystemVariable;
import com.solution.model.UserInfo;
import com.solution.model.UserQuestionMapping;
import com.solution.model.UserQuestionMappingId;
import com.solution.util.MessageCreation;
import com.solution.util.SearchVO;

public class ExamineeAction extends Action {
	/**
	 * logging instance.
	 */
	private Logger logger = Logger.getLogger(ExamineeAction.class.getName());

	/**
	 * Default method.
	 */
	public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		logger.debug("Entering :: ExamineeAction:execute()");
		ExamineeForm examineeForm =(ExamineeForm)form;
		/**
		 * Show Question Case.
		 */
		if("/examineeDashboard".equals(mapping.getPath())){
			return examineeDashboard(mapping, examineeForm, request, response);
		}
		/**
		 * Show Question Case.
		 */
		if("/showQuestion".equals(mapping.getPath())){
			return showQuestion(mapping, examineeForm, request, response);
		}
		if("/showAjaxQuestion".equals(mapping.getPath())){
			return showAjaxQuestion(mapping, examineeForm, request, response);
		}
		if("/finishExam".equals(mapping.getPath())){
			return finishExam(mapping, examineeForm, request, response);
		}
		if("/examineeLogout".equals(mapping.getPath()))
		{
			return examineeLogout(mapping, examineeForm,request);
		}
		return null;
	}
	
	public ActionForward examineeLogout(ActionMapping mapping,ExamineeForm examForm, HttpServletRequest request ) throws IOException, ServletException
    {
		return mapping.findForward("success");
    }
	
	public ActionForward examineeDashboard(ActionMapping mapping,ExamineeForm examForm,HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		logger.debug("Entering :: ExamAction:examineeDashboard()");
		ActionMessages errors  = new ActionErrors() ;
		try{
			HttpSession session = request.getSession();
			UserInfo userInfo = null;
			if(session != null){
				userInfo = (UserInfo)session.getAttribute(LoginConstants.SESSION_USER_INFO);
			}
			
			ExaminationServiceDelegate examinationServiceDelegate = new ExaminationServiceDelegate();
			ExamType examType = examinationServiceDelegate.getExam(userInfo.getExamType().getId());
			examForm.setExamType(examType);
			boolean isMultiple = examType.getMultipleChoiceEnabled()==0?false:true;
			SearchVO searchVO =  new SearchVO();
			searchVO.addEqualsCondition("id.examTypeId", userInfo.getExamType().getId(),true);
			List<ExamCategoryLevelMapping> examLevelCategoryMappingList = examinationServiceDelegate.fetchExamCategoryLevelMapping(searchVO);
			searchVO.clear();
			List<QuestionType> finalQuestionTypeList = new ArrayList<QuestionType>();
			for(ExamCategoryLevelMapping examCategoryLevelMappingTemp:examLevelCategoryMappingList){
				Set<QuestionType> questionTypeList = examinationServiceDelegate.fetchActiveQuestions(examCategoryLevelMappingTemp.getCategoryType().getId(), 
						examCategoryLevelMappingTemp.getLevelType().getId(), examCategoryLevelMappingTemp.getNumberQuestions(), userInfo.getClientType().getId(),isMultiple);
				finalQuestionTypeList.addAll(questionTypeList);
			}
			session.setAttribute(LoginConstants.EXAMINEE_QUESTIONS, finalQuestionTypeList);
			/*Used to save Question Id and Anwer ID for User*/
			
			HashMap<Long, Set<Long>> questionAnswerMapping = new HashMap<Long, Set<Long>>();
//			for(QuestionType questionType:finalQuestionTypeList){
//				questionAnswerMapping.put(questionType.getId(), null);
//			}
			
			session.setAttribute(LoginConstants.EXAMINEE_EXAM_TYPE,examType);
			session.setAttribute(LoginConstants.EXAMINEE_QUESTION_ANSWER, questionAnswerMapping);	
			session.setAttribute(LoginConstants.EXAMINEE_QUESTION_INDEX, new Integer(0));
		}
		catch(ServiceBeanException sbe){
			logger.error(sbe);
			errors.add("error", new ActionMessage("Examinee.fail.exception", sbe.getMessage()));
			examForm.setExamCreated("NO");
		}
		catch(DelegateException de){
			logger.error(de);
			errors.add("error", new ActionMessage("Examinee.dashboard.fail"));
		}
		saveErrors(request, errors);
		logger.debug("Exiting :: ExamAction:examineeDashboard()");
		return mapping.findForward("examineeDashboard");
	}
	
	public ActionForward showQuestion(ActionMapping mapping,ExamineeForm examForm,HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		logger.debug("Entering :: ExamAction:showQuestion()");
		ActionMessages errors  = new ActionErrors() ;
		try{
			HttpSession session = request.getSession();
			UserInfo userInfo = null;
			if(session != null){
				userInfo = (UserInfo)session.getAttribute(LoginConstants.SESSION_USER_INFO);
			} 

			List<QuestionType> questionTypeList =(List<QuestionType>)session.getAttribute(LoginConstants.EXAMINEE_QUESTIONS);
			Integer index = (Integer)session.getAttribute(LoginConstants.EXAMINEE_QUESTION_INDEX);
			/*Increase or decrease index*/
			//session.setAttribute(LoginConstants.EXAMINEE_QUESTION_INDEX,index+1);
			
			ExaminationServiceDelegate examinationServiceDelegate = new ExaminationServiceDelegate();
			examForm.setAnswerTypeList(examinationServiceDelegate.fetchActiveAnswers(questionTypeList.get(index).getId()));
			examForm.setExamType(examinationServiceDelegate.getExam(userInfo.getExamType().getId()));
			
			// fetch the system variable.
			SystemVariableServiceDelegate systemVariableService = new SystemVariableServiceDelegate();
			SystemVariable systemVariable = systemVariableService.getValue(SystemVariableConstants.EXAMINEE_NAVIGATION_EXPIRY_SEC, userInfo.getClientType().getId());
			
			if(systemVariable != null){
				examForm.setNavigationExpiryTime(new Long(systemVariable.getVariableValue()));
			}
		}
		catch(ServiceBeanException sbe){
			logger.error(sbe);
			errors.add("error", new ActionMessage("Exam.fail.exception", sbe.getMessage()));
		}
		catch(DelegateException de){
			logger.error(de);
			errors.add("error", new ActionMessage("Exam.details.fail"));
		}
		saveErrors(request, errors);
		logger.debug("Exiting :: ExamAction:showQuestion()");
		return mapping.findForward("examineeQuestion");
	}
	public ActionForward showAjaxQuestion(ActionMapping mapping,ExamineeForm examineeForm,HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		logger.debug("Entering :: ExamAction:showAjaxQuestion()");
			ActionMessages errors  = new ActionErrors() ;
		try{
			HttpSession session = request.getSession();
			List<QuestionType> questionTypeList =(List<QuestionType>)session.getAttribute(LoginConstants.EXAMINEE_QUESTIONS);
			Integer index = (Integer)session.getAttribute(LoginConstants.EXAMINEE_QUESTION_INDEX);
			HashMap<Long, Set<Long>> qesAnswer = (HashMap<Long,  Set<Long>>)session.getAttribute(LoginConstants.EXAMINEE_QUESTION_ANSWER);
			String answerIdsString = examineeForm.getAnswerIds();
			String answerIdsArray[] = answerIdsString.split(",");
			if(answerIdsArray.length!= 1){
				Set<Long> tempAnswerSet = qesAnswer.get(questionTypeList.get(index).getId());
				if(tempAnswerSet== null){
					tempAnswerSet = new HashSet<Long>();
				}
				else{
					tempAnswerSet.clear();
				}
				for(String answerIdstr:answerIdsArray){
					if(!"-1".equals(answerIdstr)){
						tempAnswerSet.add(new Long(answerIdstr));
					}
				}
				qesAnswer.put(questionTypeList.get(index).getId(), tempAnswerSet);
					
								
			}else {
				qesAnswer.remove(questionTypeList.get(index).getId());
			}
//			if(examineeForm.getAnswerId()!=-1){				
//				qesAnswer.put(questionTypeList.get(index).getId(), examineeForm.getAnswerId());
//			}else{
//				qesAnswer.remove(questionTypeList.get(index).getId());
//			}
			ExaminationServiceDelegate examinationServiceDelegate = new ExaminationServiceDelegate();
			
			/*Increase or decrease index*/
			if("next".equalsIgnoreCase(examineeForm.getNextOrPrevious())){
				if(index<questionTypeList.size()-1){
					session.setAttribute(LoginConstants.EXAMINEE_QUESTION_INDEX,index+1);
					examineeForm.setAnswerTypeList(examinationServiceDelegate.fetchActiveAnswers(questionTypeList.get(index+1).getId()));					
				}else{
					examineeForm.setAnswerTypeList(examinationServiceDelegate.fetchActiveAnswers(questionTypeList.get(index).getId()));					
				}
			}else{
				if(index>0){
					session.setAttribute(LoginConstants.EXAMINEE_QUESTION_INDEX,index-1);
					examineeForm.setAnswerTypeList(examinationServiceDelegate.fetchActiveAnswers(questionTypeList.get(index-1).getId()));					
				}else{
					examineeForm.setAnswerTypeList(examinationServiceDelegate.fetchActiveAnswers(questionTypeList.get(index).getId()));					
				}
			}
			
			
			
		}
		catch(ServiceBeanException sbe){
			logger.error(sbe);
			errors.add("error", new ActionMessage("Exam.fail.exception", sbe.getMessage()));
		}
		catch(DelegateException de){
			logger.error(de);
			errors.add("error", new ActionMessage("Exam.details.fail"));
		}
		saveErrors(request, errors);
		logger.debug("Exiting :: ExamAction:showAjaxQuestion()");
		return mapping.findForward("examineeAjaxQuestion");
	}
	public ActionForward finishExam(ActionMapping mapping,ExamineeForm examineeForm,HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		logger.debug("Entering :: ExamAction:finishExam()");
			ActionMessages errors  = new ActionErrors() ;
		try{
			ExaminationServiceDelegate examinationServiceDelegate = new ExaminationServiceDelegate();
			UserInfoServiceDelegate userService = new UserInfoServiceDelegate();
			HttpSession session = request.getSession();
			UserInfo userInfo = null;
			if(session != null){
				userInfo = (UserInfo)session.getAttribute(LoginConstants.SESSION_USER_INFO);				
			} 			
			HashMap<Long, Set<Long>> quesAnswer = (HashMap<Long, Set<Long>>)session.getAttribute(LoginConstants.EXAMINEE_QUESTION_ANSWER);
			List<UserQuestionMapping> userQuestionMappingList = new ArrayList<UserQuestionMapping>();
			List<QuestionType> questionTypeList =(List<QuestionType>)session.getAttribute(LoginConstants.EXAMINEE_QUESTIONS);
			Iterator<QuestionType> questionItr = questionTypeList.iterator();
			QuestionType questionType = null;
			AnswerType answerType = null;
			UserQuestionMapping userQuestionMapping = null;
			UserQuestionMappingId userQuestionMappingId = null;
			double correctAnswerScore = 0;
			double wrongAnswerScore = 0;
			Date createdOn = new Date();
			ExamType examType = examinationServiceDelegate.getExam(userInfo.getExamType().getId());
			short isNegativeMarking = examType.getNegativeEnabled().shortValue();
			while(questionItr.hasNext())
			{
				questionType = questionItr.next();
				
				if(quesAnswer.get(questionType.getId())!=null){
					Set<Long> markedAnswerSet = quesAnswer.get(questionType.getId()); //Temporary comment
					
					List<AnswerType> correctAnswerList = examinationServiceDelegate.fetchCorrectAnswer(questionType.getId());
					
						for(Long ansId : markedAnswerSet){							
							userQuestionMapping = new UserQuestionMapping();
							userQuestionMappingId = new UserQuestionMappingId();
							userQuestionMappingId.setUserInfoId(userInfo.getId());
							userQuestionMappingId.setQuestionTypeId(questionType.getId());
							userQuestionMappingId.setMarkedAnswerTypeId(ansId);
							userQuestionMapping.setId(userQuestionMappingId);
							userQuestionMapping.setCreatedBy(userInfo.getUsername());
							userQuestionMapping.setCreatedOn(createdOn);							
							userQuestionMapping.setQuestionType(questionType);
							userQuestionMapping.setUserInfo(userInfo);								
							
							answerType = new AnswerType();
							answerType.setId(ansId);							
							userQuestionMapping.setAnswerType(answerType);
							userQuestionMappingList.add(userQuestionMapping);
							
							
						}
						/*Marking Logic Starts here for multiple select */
						if(examType.getMultipleChoiceEnabled()==1){
								List<Long> correctAnswerIdList = new ArrayList<Long>();
								for(AnswerType ansType:correctAnswerList){
									correctAnswerIdList.add(ansType.getId());
								}
								boolean allCorrectThere = markedAnswerSet.containsAll(correctAnswerIdList);
								if(allCorrectThere && (markedAnswerSet.size()==correctAnswerIdList.size())){
									correctAnswerScore = correctAnswerScore+questionType.getLevelType().getPositiveMark();							
								}
						}else{ /*Marking Logic Starts here for single choice exam */				
						
							if(quesAnswer.get(questionType.getId()).contains(correctAnswerList.get(0).getId().longValue())){
								correctAnswerScore = correctAnswerScore+questionType.getLevelType().getPositiveMark();
							}
							else{
								if(isNegativeMarking == 1){
									wrongAnswerScore = wrongAnswerScore+questionType.getLevelType().getNegativeMark();
								}
							}
						}
						
					
				}else{
					/*if Question is not attempted*/
					userQuestionMapping = new UserQuestionMapping();
					userQuestionMappingId = new UserQuestionMappingId();
					userQuestionMappingId.setUserInfoId(userInfo.getId());
					userQuestionMappingId.setQuestionTypeId(questionType.getId());
					answerType = new AnswerType();
					answerType.setId(1l);			
					userQuestionMappingId.setMarkedAnswerTypeId(answerType.getId());
					
					userQuestionMapping.setId(userQuestionMappingId);
					userQuestionMapping.setCreatedBy(userInfo.getUsername());
					userQuestionMapping.setCreatedOn(createdOn);							
					userQuestionMapping.setQuestionType(questionType);
					userQuestionMapping.setUserInfo(userInfo);	
					
					userQuestionMapping.setAnswerType(answerType);
					userQuestionMappingList.add(userQuestionMapping);
				}
			}
			userService.createUserQuestionMappings(userQuestionMappingList); //temporary blocked
			double score = correctAnswerScore - wrongAnswerScore;
			userInfo.setExamScore(score);
			userInfo.setStatus(LoginConstants.USER_BLOCKED);//temporary blocked
			userInfo.setModifiedOn(new Date());
			userInfo.setModifiedBy(userInfo.getUsername());
			userService.update(userInfo);
			
			sendEmailSMS(userInfo);
		}
		catch(ServiceBeanException sbe){
			logger.error(sbe);
			errors.add("error", new ActionMessage("Exam.fail.exception", sbe.getMessage()));
		}
		catch(DelegateException de){
			logger.error(de);
			errors.add("error", new ActionMessage("Exam.details.fail"));
		}
		saveErrors(request, errors);
		logger.debug("Exiting :: ExamAction:finishExam()");
		return mapping.findForward("finishExam");
	}

	private void sendEmailSMS(UserInfo examinee) throws DelegateException, ServiceBeanException{
		
		String subject = "iPariksha Inc. : Score for Exam";
		CommunicationServiceDelegate communicationServiceDelegate = new CommunicationServiceDelegate();
		SystemVariableServiceDelegate systemVariableService = new SystemVariableServiceDelegate();
		ExaminationServiceDelegate examinationServiceDelegate = new ExaminationServiceDelegate();
		ExamType exam = examinationServiceDelegate.getExam(examinee.getExamType().getId());
		if(examinee.getContactType() != null && examinee.getContactType().getEmail() != null 
			&& !"".equals(examinee.getContactType().getEmail().trim())){
			SystemVariable systemVariable = systemVariableService.getValue(SystemVariableConstants.EXAMINEE_SCORE_EXAMINEE_EMAIL, examinee.getClientType().getId());
			if("1".equals(systemVariable.getVariableValue().trim())){
				if(exam != null){
					Map<String, String> variableStrings = new HashMap<String, String>();
					variableStrings.put("firstName", examinee.getFirstName());
					variableStrings.put("examName", exam.getName());
					variableStrings.put("score", examinee.getExamScore().toString());
					// Build the dynamic content.
					String emailContent = MessageCreation.getMessage(variableStrings, "conf/ExamineeScore.vm");
					communicationServiceDelegate.sendEmail(examinee.getContactType().getEmail(), emailContent, subject, 
						examinee.getClientType().getId(), examinee.getUsername());
				}
			}
		}
		
		SystemVariable systemVariable = systemVariableService.getValue(SystemVariableConstants.EXAMINEE_SCORE_EXAMINER_EMAIL, examinee.getClientType().getId());
		
		if("1".equals(systemVariable.getVariableValue().trim())){
			UserInfoServiceDelegate userInfoServiceDelegate = new UserInfoServiceDelegate();
			SearchVO searchVO = new SearchVO();
			searchVO.addEqualsCondition("clientType.id", examinee.getClientType().getId(), true);
			searchVO.addEqualsCondition("status", LoginConstants.USER_ACTIVE);
			searchVO.addEqualsCondition("userPriviledge", new Short("2"));
			List<UserInfo> examiners = userInfoServiceDelegate.searchUser(searchVO);
			if(examiners != null && examiners.size()>0){
				for(UserInfo examiner : examiners){
					if(examiner.getContactType() != null && examiner.getContactType().getEmail() != null 
						&& !"".equals(examiner.getContactType().getEmail().trim())){
						Map<String, String> variableStrings = new HashMap<String, String>();
						variableStrings.put("firstName", examinee.getFirstName());
						variableStrings.put("examName", exam.getName());
						variableStrings.put("score", examinee.getExamScore().toString());
						// Build the dynamic content.
						String emailContent = MessageCreation.getMessage(variableStrings, "conf/ExamineeScore.vm");
						communicationServiceDelegate.sendEmail(examiner.getContactType().getEmail(), emailContent, subject, 
							examiner.getClientType().getId(), examiner.getUsername());
					}
				}
			}
		}
	}
}
